<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Mapper\ChCustomerServiceLinkMapper;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChUserMapper;
use App\CustHub\Model\ChCustomerServiceLinkRobotRelation;
use App\Robot\Dto\RobotMsgDto;
use App\Robot\Job\SendRobotMsgDelayedJob;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Paginator\LengthAwarePaginator;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Mine\MineModel;
use function Hyperf\Collection\data_get;

class ChCustomerServiceLinkService extends AbstractService
{
    #[Inject]
    protected ChRobotMapper $robotMapper;

    #[Inject]
    protected ChUserMapper $userMapper;

    #[Inject]
    protected ChRobotService $robotService;

    #[Inject]
    protected ChCustomerServiceLinkRobotRelation $robotRelation;

    public $mapper;

    public function __construct(ChCustomerServiceLinkMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function getLinkList(array $params)
    {
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;

        // 子查询：统计每个 link_id 的机器人数量
        $robotCountSubQuery = ChCustomerServiceLinkRobotRelation::query()
            ->selectRaw('link_id, COUNT(robot_id) as robot_count')
            ->groupBy('link_id');

        // 主查询
        $paginate = $this->mapper->model::query()
            ->from('ch_customer_service_link as link')
            ->leftJoinSub($robotCountSubQuery, 'robot_counts', function ($join) {
                $join->on('link.id', '=', 'robot_counts.link_id');
            })
            ->select([
                'link.id',
                'link.name',
                'link.hits',
                'link.total_hits',
                'link.created_at',
                'link.link',
                'a.nickname as user_name',
                Db::raw('COALESCE(robot_counts.robot_count, 0) as robot_count') // 默认为 0
            ])
            ->leftJoin('ch_user as a', 'a.id', '=', 'link.uid')
            ->where('link.uid', $params['uid'])
            ->when(!empty($params['name']), function ($query) use ($params) {
                $query->where('link.name', 'like', '%' . $params['name'] . '%');
            })
            ->orderBy('link.id', 'desc')
            ->paginate($pageSize);

        return $this->mapper->setPaginate($paginate);
    }

    public function getRobotListByLink($params)
    {
        $page = (int)($params['page'] ?? 1);
        $pageSize = (int)$params['page_size'] ?? MineModel::PAGE_SIZE;
        $ids = $this->robotRelation::query()
            ->where('link_id', $params['link_id'])
            ->value('robot_ids') ?? [];
        $customerServiceList = $this->robotMapper->findByIds($ids,'avatar,nickname')->toArray();

        $offset = ($page - 1) * $pageSize;
        $paginatedItems = array_slice($customerServiceList, $offset, $pageSize);

        $paginate = new LengthAwarePaginator(
            $paginatedItems,
            count($customerServiceList),
            $pageSize,
            $page
        );

        return $this->mapper->setPaginate($paginate);
    }

    public function checkRepeat($uid, $name, $id = 0)
    {
        if ($id == 0) {
            return $this->mapper->model::where('uid', $uid)->where('name', $name)->exists();
        }
        return $this->mapper->model::where('uid', $uid)->where('id', '<>', $id)->where('name', $name)->exists();
    }

    public function saveLink($params)
    {
        $data['created_at'] = date('Y-m-d H:i:s',time());

        $data = $this->handleDate($params);
        $this->deleteCache($params['uid']);
        $linkId = $this->save($data);

        // 获取 robot_list 数据
        $robotList = $data['robot_list'];
        // 如果 robot_list 不为空，则插入到 ch_customer_service_link_robot_relation 表
        $this->addRobotToRelation($linkId, $robotList);

        return $linkId;
    }

    public function updateLink($params): bool
    {
        $data = $this->handleDate($params);
        $linkId = (int)$data['id'];
        $uid = (int)$params['uid'];

        // 删除缓存
        $this->deleteCache($uid);

        // 1. 更新主表 ch_customer_service_link
        $result = $this->update($linkId, $data);
        if (!$result) {
            return false;
        }

        // 2. 获取新的 robot_list 数据
        $robotList = $data['robot_list'];

        // 3. 先删除旧的关联记录
        $this->deleteRobotFromRelation($linkId);

        $this->addRobotToRelation($linkId, $robotList);

        return true;
    }

    public function deleteLink($params)
    {
        $id = $params['id'];
        $link = $this->mapper->model::find($id);
        if (!$link) {
            return false;
        }
        $this->deleteCache($params['uid']);
        $this->deleteRobotFromRelation($id);
        return $this->mapper->delete((array)$id);
    }

    public function randomQrcode(array $data)
    {
        $linkRecord = $this->mapper->findByLink($data['link']);
        $linkId = $linkRecord->id ?? 0;

        // 1. 获取链接记录
//        $linkRecord = $this->mapper->findById($linkId);
        if (!$linkRecord) {
            throw new NormalStatusException('链接不存在');
        }

        // 2. 获取所有可用机器人
        $robots = $this->robotRelation::query()
            ->where('link_id', $linkId)
            ->where('is_show', 1)
            ->get(['robot_id', 'daily_visit', 'total_visit', 'visit_limit', 'sort'])
            ->toArray();

        if (empty($robots)) {
            throw new NormalStatusException('暂无客服');
        }

        // 3. 过滤掉已达访问上限的机器人
        $availableRobots = array_filter($robots, function ($robot) use ($linkRecord) {
            $limit = $robot['visit_limit'] ?? 0;

            if ($linkRecord->qrcode_vc_type === 1) { // 每日限制
                return $robot['daily_visit'] < $limit;
            } else { // 累计限制
                return $robot['total_visit'] < $limit;
            }
        });

        if (empty($availableRobots)) {
            throw new NormalStatusException('所有客服已达到访问上限');
        }

        // 4. 根据 visit_type 选择机器人
        $robotId = $this->selectRobotByVisitType($linkRecord, $availableRobots);

        // 5. 递增访问计数（事务处理）
        Db::beginTransaction();
        try {
            $this->robotRelation::query()
                ->where('link_id', $linkId)
                ->where('robot_id', $robotId)
                ->incrementEach([
                    'daily_visit' => 1,
                    'total_visit' => 1
                ]);

            $this->mapper->model::query()
                ->where('id', $linkId)
                ->incrementEach([
                    'hits' => 1,
                    'total_hits' => 1
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollBack();
            throw $e;
        }

        // 6. 获取并返回二维码
        return $this->robotService->getPersonalQRCode([
            'uid' => $linkRecord->uid,
            'id' => $robotId
        ]);
    }

    private function handleDate(array $data): array
    {
        $data['robot_list'] = json_decode($data['robot_list'], true) ?? [];
        $data['greeting_head'] = json_decode($data['greeting_head'], true) ?? null;
        $data['greeting_body'] = json_decode($data['greeting_body'], true) ?? null;
        $data['greeting_end'] = json_decode($data['greeting_end'], true) ?? null;
        $data['page_cfg'] = json_decode($data['page_cfg'], true) ?? null;
        return $data;
    }

    public function getLinkDetail($params)
    {
        $linkId = (int)$params['id'];

        // 1. 获取主表数据
        $link = $this->mapper->findById($linkId);
        if (!$link) {
            return null;
        }

        // 2. 查询关联的机器人信息及配置
        $robots = $this->robotRelation::query()
            ->where('link_id', $linkId)
            ->get(['robot_id', 'is_show', 'sort', 'visit_limit'])
            ->toArray();

        $robotIds = array_column($robots, 'robot_id');

        // 新增：通过 robotMapper 获取机器人昵称
        if (!empty($robotIds)) {
            // 修改点：调用 toArray() 将 MineCollection 转换为原生数组
            $robotNicknames = $this->robotMapper->findByIds($robotIds, 'id,nickname')->toArray();
            $nicknameMap = array_column($robotNicknames, 'nickname', 'id'); // 构建 ID => nickname 映射

            // 将昵称拼接到 robots 中
            foreach ($robots as &$robot) {
                $robot['nickname'] = $nicknameMap[$robot['robot_id']] ?? '未知客服'; // 若未找到昵称则标记为未知
            }
        }

        // 3. 将机器人信息附加到主表对象中
        $link['robots_list'] = $robots;

        return $link;
    }

    public function addTask($data)
    {
        $robotId = (int)$data['robot_id'];
        $uid = (int)$data['uid'];
        $linkRecord = $this->mapper->findByRobotIdAndUid($robotId, $uid);
        if (!$linkRecord) {
            return;
        }
        $greetingHead = data_get($linkRecord['greeting_head'], 'greeting_head') ?? [];
        $greetingBody = data_get($linkRecord['greeting_body'], 'greeting_body') ?? [];
        $greetingEnd = data_get($linkRecord['greeting_end'], 'greeting_end') ?? [];
        $this->sendMessage($greetingHead, $data);
        sleep(5);
        $this->sendMessage($greetingBody, $data);
        sleep(5);
        $this->sendMessage($greetingEnd, $data);
    }

    private function sendMessage(array $messages, array $data): void
    {
        if (empty($messages)) {
            return;
        }

        foreach ($messages as $item) {

            $messageItem = $this->normalizeMessageContent($item['content']);

            foreach ($messageItem as $index => $msg) {

                $robotId = $data['robot_id'] ?? null;

                $robotInfo = $this->robotMapper->findById($robotId);
                if (empty($robotInfo) || $robotInfo['login_status'] != 1) {
                    return;
                }

                $msgData = new RobotMsgDto();
                $msgData->setMsgType($msg['msg_type'] ?? 'text')
                    ->setContent($msg['content'] ?? '')
                    ->setToId($data['to_id'])
                    ->setServerId($robotInfo->server_id)
                    ->setUuid($robotInfo->uuid);

                $delay = $index > 0 ? rand(2, 5) : 0;
                container()->get(LowQueueService::class)->push(new SendRobotMsgDelayedJob($msgData), $delay);
            }
        }
    }

    public function usedRobotIds(array $params):array
    {
        $key = "get_used_robot_ids:".$params['uid'];
        $ids = redis()->get($key);
        if ($ids) {
            return $ids;
        }
        $uid = (int)$params['uid'];
        // 2. 查询当前用户下的所有 link_id
        $linkIds = $this->mapper->model::query()
            ->where('uid', $uid)
            ->pluck('id')
            ->toArray();

        if (empty($linkIds)) {
            redis()->set($key, '[]', 10 * 60); // 缓存空数组
            return [];
        }

        // 3. 根据 link_id 查询所有已使用的 robot_id
        $result = ChCustomerServiceLinkRobotRelation::query()
            ->whereIn('link_id', $linkIds)
            ->distinct()
            ->pluck('robot_id')
            ->toArray();

        redis()->set($key, $result,10 * 60);

        return $result;
    }

    public function reset(): void
    {
        $this->mapper->model::query()->update(['hits' => 0]);

        $this->robotRelation::query()->update(['daily_visit' => 0]);
    }

    private function normalizeMessageContent($content): array
    {
        // 情况1：已经是多条消息的数组
        if (is_array($content) && isset($content[0]['content'])) {
            return $content;
        }

        // 情况2：单条消息格式
        if (is_array($content) && isset($content['content'])) {
            return [$content];
        }

        // 情况3：无效格式
        return [];
    }

    private function deleteCache($uid): void
    {
        $key = "get_used_robot_ids:".$uid;
        redis()->del($key);
    }

    private function deleteRobotFromRelation($linkId)
    {
        $this->robotRelation::query()
            ->where('link_id', $linkId)
            ->delete();
    }

    private function addRobotToRelation($linkId, $robotList)
    {
        if (!empty($robotList) && is_array($robotList)) {
            foreach ($robotList as $robotInfo) {
                $robotId = (int)$robotInfo['robot_id']; // 机器人 ID
                $isShow = (int)$robotInfo['is_show'];   // 是否展示
                $sort = (int)$robotInfo['sort'];        // 排序值
                $visitLimit = (int)$robotInfo['visit_limit']; // 访问上限

                // 插入到 ch_customer_service_link_robot_relation 表
                $this->robotRelation::query()->insert([
                    'link_id' => $linkId,
                    'robot_id' => $robotId,
                    'is_show' => $isShow,
                    'sort' => $sort,
                    'daily_visit' => 0,
                    'total_visit' => 0,
                    'visit_limit' => $visitLimit
                ]);
            }
        }
    }

    private function selectRobotByVisitType($linkRecord, array $availableRobots)
    {
        $visitType = $linkRecord->visit_type;

        $robotIds = array_column($availableRobots, 'robot_id');
        switch ($visitType) {
            case 2: // 随机跳转
                return $robotIds[array_rand($robotIds)];

            case 3: // 轮询访问（循环选择）
                $key = "link:robot:index:{$linkRecord->id}";
                $currentIndex = (int)(redis()->get($key) ?? 0);
                $robotCount = count($robotIds);
                $index = $currentIndex % $robotCount;
                $nextIndex = ($index + 1) % $robotCount;
                redis()->set($key, $nextIndex, 86400); // 每日重置
                return $robotIds[$index];

            case 4: // 顺序切换（始终选择第一个可用机器人）
                return $robotIds[0]; // 始终选择排序后的第一个机器人

            default:
                throw new NormalStatusException('不支持的访问方式');
        }
    }
}